import SparkMD5 from 'spark-md5'
import { obs_completeSegmented, obs_initSegmented, obs_uploadSegmented } from '@/apiList/apiHuaweiObskLM'

/**
 * 获取文件 buffer
 * @param {File} file
 * @returns
 */
function fileParseBuf(file) {
  return new Promise((resolve) => {
    const fileRead = new FileReader()
    fileRead.readAsArrayBuffer(file)
    fileRead.onload = (ev) => {
      resolve(ev.target.result)
    }
  })
}
/**
 * 分片上传
 */
export class SliceUploadFile {
  constructor() {
    /**上传的文件 */
    this.file = null
    /**文件md5值 */
    this.md5Hash = ''
    /**上传任务id */
    this.uploadId = ''
    /**分片大小（mb） */
    this.chunkSize = 2
    /**文件分片列表 */
    this.partList = []
    /**上传的文件大小 */
    this.uploadSize = 0
    /**文件总大小 */
    this.fileSizeTotal = 0
    /**已上传的文件分片列表 */
    this.uploadPartList = []
  }
  // 上传进度条计算
  uploadProgress() {
    var count = 0
    if (this.fileSizeTotal > 0) {
      count = (this.uploadSize / this.fileSizeTotal) * 100
    }
    return parseFloat(count.toFixed(2))
  }
  /**
   * 初始化上传任务
   * @param {File} file
   * @returns
   */
  async initSegmented(file) {
    if (!(file instanceof File)) return console.log('请上传文件')
    const buffer = await fileParseBuf(file)
    const spark = new SparkMD5.ArrayBuffer()
    spark.append(buffer)
    const hash = spark.end()
    const suffix = /\.([\w]+)$/i.exec(file.name)[1]
    const res = await obs_initSegmented({
      contentType: suffix,
      dir: 'video',
      fileName: file.name,
      md5: hash
    })
    // 保存初始化信息
    this.file = file
    this.md5Hash = hash
    this.uploadId = res.uploadId
    this.fileSizeTotal = this.file.size
    this.uploadPartList = res.etags || []
  }
  /**创建文件切片 */
  createFileSliceList() {
    let i = 0,
      cur = 0,
      partList = [],
      size = this.file.size,
      partsize = this.chunkSize * 1024 * 1024
    while (size > 0) {
      let currentSize = partsize
      if (size < partsize) {
        currentSize = partsize - size
      }
      let item = {
        offset: cur,
        partSize: currentSize,
        number: i + 1,

        chunk: this.file.slice(cur, cur + currentSize),
        filename: `${this.md5Hash}_${i++}`
      }
      cur += currentSize
      size -= currentSize
      partList.push(item)
    }

    this.partList = partList
  }
  // 2.创建请求合集
  createRequestList() {
    // 获取一下服务器已有的切片列表，然后只添加服务器没有的切片
    const notList = [] // 未上传
    const alreadyList = [] // 已上传
    this.partList.forEach((item, index) => {
      if (this.uploadPartList.some((x) => x.partNumber - 1 == index)) {
        alreadyList.push(item)
      } else {
        notList.push(item)
      }
    })
    // 添加已上传的大小
    this.uploadSize = alreadyList.reduce((p, c) => {
      p += c.chunk.size
      return p
    }, 0)
    // 根据切片创建请求参数集合
    let requestList = notList.map((item) => {
      let formData = new FormData()
      formData.append('md5', this.md5Hash)
      formData.append('file', item.chunk)
      formData.append('offset', item.offset)
      formData.append('number', item.number)
      formData.append('partSize', item.partSize)
      formData.append('uploadId', this.uploadId)
      return { ...item, formData }
    })
    return requestList
  }
  /**
   * 发送文件分片合集
   * @param {File} file
   * @param {function} progress
   */
  async sendRequest(file, progress) {
    await this.initSegmented(file)
    this.createFileSliceList()
    let requestList = this.createRequestList()
    for (let item of requestList) {
      // 此处以后可以优化为 多片段并发 使用 promise.all
      await obs_uploadSegmented(item.formData)
      if (typeof progress == 'function') {
        progress(this.uploadProgress())
      }
      console.log(item.number)
      this.uploadSize += item.chunk.size
    }
    // 4.都传完了通知服务器合并文件
    const result = await obs_completeSegmented({ md5: this.md5Hash, uploadId: this.uploadId })
    console.log(result, '-->>> 文件上传完成')
    return result
  }
}
